package cn.wildfirechat.app.shiro;

import cn.wildfirechat.app.RestResult;
import cn.wildfirechat.app.jpa.*;
import cn.wildfirechat.app.jpa.Record;
import cn.wildfirechat.app.pojo.SessionOutput;
import cn.wildfirechat.app.tools.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;

import static cn.wildfirechat.app.RestResult.RestCode.*;
import static cn.wildfirechat.app.jpa.PCSession.PCSessionStatus.*;

@Service
public class AuthDataSource {
    private static final Logger LOG = LoggerFactory.getLogger(AuthDataSource.class);

    @Autowired
    private PCSessionRepository pcSessionRepository;

    @Autowired
    private RecordRepository recordRepository;

    @Autowired
    private EmailRecordRepository emailRecordRepository;

    public RestResult.RestCode insertEmailRecord(String email, String code) {
        if (!Utils.isEmail(email)) {
            LOG.error("Not valid email {}", email);
            return RestResult.RestCode.ERROR_INVALID_MOBILE;
        }

        EmailRecord record = emailRecordRepository.findById(email).orElseGet(() -> new EmailRecord(code, email));

        if (System.currentTimeMillis() - record.getTimestamp() < 60 * 1000) {
            LOG.error("Send code over frequency. timestamp {}, now {}", record.getTimestamp(), System.currentTimeMillis());
            return RestResult.RestCode.ERROR_SEND_SMS_OVER_FREQUENCY;
        }

        if (!record.increaseAndCheck()) {
            LOG.error("Count check failure, already send {} messages today", record.getRequestCount());
            RestResult.RestCode c = RestResult.RestCode.ERROR_SEND_SMS_OVER_FREQUENCY;
            c.msg = "发送给用户 " + email + " 超出频率限制";
            return c;
        }

        record.setCode(code);
        record.setTimestamp(System.currentTimeMillis());
        emailRecordRepository.save(record);
        return RestResult.RestCode.SUCCESS;
    }

    public void clearRecode(String mobile) {
        try {
            recordRepository.deleteById(mobile);
        } catch (Exception e) {
        }
    }

    public RestResult.RestCode verifyCode(String mobile, String code) {
        Optional<Record> recordOptional = recordRepository.findById(mobile);
        if (!recordOptional.isPresent()) {
            LOG.error("code not exist");
            return RestResult.RestCode.ERROR_CODE_INCORRECT;
        }
        if(!recordOptional.get().getCode().equals(code)) {
            LOG.error("code not matched");
            return RestResult.RestCode.ERROR_CODE_INCORRECT;
        }

        if (System.currentTimeMillis() - recordOptional.get().getTimestamp() > 5 * 60 * 1000) {
            LOG.error("Code expired. timestamp {}, now {}", recordOptional.get().getTimestamp(), System.currentTimeMillis());
            return RestResult.RestCode.ERROR_CODE_EXPIRED;
        }
        return RestResult.RestCode.SUCCESS;
    }

    public PCSession getSession(String token, boolean clear) {
        Optional<PCSession> session = pcSessionRepository.findById(token);
        if (clear) {
            pcSessionRepository.deleteById(token);
        }
        return session.orElse(null);
    }

    public void saveSession(PCSession session) {
        pcSessionRepository.save(session);
    }

    public RestResult.RestCode checkPcSession(String token) {
        Optional<PCSession> session = pcSessionRepository.findById(token);
        if (session.isPresent()) {
            if (session.get().getStatus() == Session_Verified) {
                //使用用户id获取token
                return SUCCESS;
            } else {
                if (session.get().getStatus() == Session_Created) {
                    return ERROR_SESSION_NOT_SCANED;
                } else if (session.get().getStatus() == Session_Canceled) {
                    return ERROR_SESSION_CANCELED;
                } else {
                    return ERROR_SESSION_NOT_VERIFIED;
                }
            }
        } else {
            return RestResult.RestCode.ERROR_SESSION_EXPIRED;
        }
    }

    public RestResult.RestCode verifyEmailCode(String email, String code) {
        Optional<EmailRecord> recordOptional = emailRecordRepository.findById(email);
        if (recordOptional.isEmpty()) {
            LOG.error("code not exist");
            return RestResult.RestCode.ERROR_CODE_INCORRECT;
        }
        if(!recordOptional.get().getCode().equals(code)) {
            LOG.error("code not matched");
            return RestResult.RestCode.ERROR_CODE_INCORRECT;
        }

        if (System.currentTimeMillis() - recordOptional.get().getTimestamp() > 5 * 60 * 1000) {
            LOG.error("Code expired. timestamp {}, now {}", recordOptional.get().getTimestamp(), System.currentTimeMillis());
            return RestResult.RestCode.ERROR_CODE_EXPIRED;
        }
        return RestResult.RestCode.SUCCESS;
    }
}
